# -*- coding: utf-8 -*-
"""产品预订"""
import json
import copy
import datetime
import uuid

from flask import Blueprint, jsonify, request, g, current_app, abort, \
    render_template
from flask.views import MethodView, View
from mongoengine import Q

from app.utils.html5 import Html5BaseMixin, wrap_h5
from app.models import Product, Mtu, ProductSKU, UserPlan, Order, HotelProductOrder
from app.constants import MTU_TYPE, form_field_dict, GDS_ORDER_STATUS, API_ORDER_ERROR
from app.utils import safe_int, smart_str, get_objectId, api_ok, api_error, check_object_ids
from app.controllers import get_productsku_blackout_date, book_utils
from app.forms.order import OrderKwargsForm


# __all__ = ['order']
# order = Blueprint('order', __name__)


class OrderView(MethodView, Html5BaseMixin):
    """
    这个是新接口 仅JSON交互
    产品订单处理(用户填写订单页面)

    # 旧方法移除
    get_user_agent_info : 在self._init_data 里处理
    """

    def get_order_or_none(self, order_id):
        # 需求：检查用户是否在修改订单

        if not order_id:
            return None

        return Order.objects.filter(id=order_id, status=1).first()

    def get(self, product_id):
        data = wrap_h5(request)

        # TODO 需求：超员费 -> 在ProductSKU添加

        # 获取参数并校验
        product_id = get_objectId(product_id)
        if not product_id:
            return api_error(msg=u'产品ID不能为空')

        kwargs_form = OrderKwargsForm(request.args)
        if not kwargs_form.validate():
            return api_error(detail=kwargs_form.errors)

        data.update(kwargs_form.data)

        condition = Q(id=product_id) & Q(is_active=True) & Q(published=True)
        product = Product.objects.filter(condition).first()

        if not product:
            return api_error(msg=u'找不到该产品!')
        # FIXME zezhou 旧方法在这里会判断模板id，如果是保险产品会跳转到特殊链接处理

        # FIXME zezhou 在获取订单信息时候，为什么需要给产品产品赋值mtu
        mtu = Mtu.objects.filter(target_type=MTU_TYPE.PRODUCT, target_id=str(product.id)).first()
        if not mtu:
            return api_error(msg=u'找不到该产品的MTU!')

        product.mtu_id = mtu.pk

        order = self.get_order_or_none(kwargs_form.order_id.data)

        # FIXME zezhou 原先的is_vacation用于区分面包旅行和自由行（两者在同个Django程序下，这里应该不需要了, 暂时保留
        # 在自由行中，如果订单来自某个计划，则显示底部广告
        data['is_show_bottom_banner'] = False
        if data['is_vacation']:
            if kwargs_form.plan_id.data or (order and order.plan_id):
                data['is_show_bottom_banner'] = True


        # 需求：前端需要知道是否可以显示"添加新购买类型" 的按钮 -- old设计:is_add_product_type
        data['has_multi_sku'] = len(product.productskus) > 1

        # data['is_baby'] = is_baby # TODO zezhou, 这个还需要么?在单品的信息里，已经有这个属性

        # 构建订单中需要显示、和填写的订单数据
        if order:
            # 用户编辑订单
            # 获取用户在订单上已经填写过的信息, 满足用户可再次编辑订单的需求
            data['order_data'] = book_utils.get_order_data(order)
        else:
            data['order_data'] = book_utils.get_order_form_data(product)

        # 返回产品信息
        # data['product'] = product.as_dict()

        return api_ok(data)

    def post(self, product_id):
        """
        前端传值格式（JSON）：
            {
                "custom_option": {},
                "detail": {},
            }
        """
        data = wrap_h5(request)

        product_id = get_objectId(product_id)
        if not product_id:
            return api_error(msg=u'产品ID不能为空')
        condition = Q(id=product_id) & Q(is_active=True) & Q(published=True)
        product = Product.objects.filter(condition).first()
        if not product:
            return api_error(msg=u'找不到该产品!')

        kwargs_form = OrderKwargsForm(request.args)
        if not kwargs_form.validate():
            return api_error(detail=kwargs_form.errors)

        mtu = Mtu.objects.filter(target_type=MTU_TYPE.PRODUCT, target_id=str(product.id)).first()
        if not mtu:
            return api_error(msg=u'找不到该产品的MTU!')
        product.mtu_id = mtu.pk

        # TODO 通过wtf 校验订单需要的数据， 如预订日期是否合法，校验detail、custom_option, product sku
        # form = OrderFrom(request.json)
        # if form.validate()....
        # data = form.data
        data = {}

        order = self.get_order_or_none(kwargs_form.order_id.data)
        if order:
            order.__dict__.update(data)
        else:
            order = Order(**data)

        order.save()


current_app.add_url_rule('/product/<product_id>/order/', view_func=OrderView.as_view('order_view'))


@current_app.route('/vacation/plan/<plan_id>/orders_inspection/')
def check_orders_in_plan(plan_id):
    """
    检查计划的订单是否可结算

    #### 请求参数

    参数名 | 必须 | 类型 | 说明
    ---- | ---- | ---- | ----
    order_ids | Y | char | 订单ids, json数据，如[1, 2, 3, 4]

    #### 返回结果
    """
    plan_id = get_objectId(plan_id)
    if not plan_id:
        return api_error(msg=u'计划ID不合法')
    plan = UserPlan.objects.filter(id=plan_id)
    if not plan:
        return api_error(msg=u'该计划找不到')
    try:
        order_ids = json.dumps(request.args.get('order_ids'))
    except Exception as e:
        return api_error(msg=u'请用JSON格式传递order_ids', detail=e)

    # 分开产品订单和酒店订单
    product_order_ids, hotel_order_ids = [], []
    for i in order_ids:
        if 'HOTEL_' in str(i):
            hotel_order_ids.append(safe_int(i.replace('HOTEL_', '')))
        else:
            product_order_ids.append((safe_int(i)))

    if product_order_ids and not check_object_ids(product_order_ids):
        return api_error(msg='非法产品ID')

    ret = book_utils.check_orders_before_pay(product_order_ids, plan=plan)

    # 酒店订单
    if hotel_order_ids and not check_object_ids(hotel_order_ids):
        return api_error(msg='非法酒店ID')

    hotel_orders = HotelProductOrder.objects.filter(
        id__in=hotel_order_ids, plan=plan, status=GDS_ORDER_STATUS['NEW'])

    for order in hotel_orders:
        if order.is_available:
            continue
        ret['is_correct'] = False
        ret['message'] = API_ORDER_ERROR.HOTEL_DATE_ERROR
        break
    return ret
